#include "CEUtilities.h"

#include "CEGUIManager.h"
#include "CEGUIContainer.h"


CEGUIContainer::CEGUIContainer(CEGUIContainer * parentContainer, int id, string name, 
							   int offsetX, int offsetY, int width, int height, bool visible)
				: CEGUIElementBase(parentContainer, id, name, offsetX, offsetY, width, height, true, visible, 0, false)
{
	m_eType = GUI_Container;
}

CEGUIContainer::~CEGUIContainer()
{
	FinalCleanUp();
}


CEGUIElementBase * CEGUIContainer::GetElement(const string& sName) const
{
	for(unsigned int i=0; i < m_pElementVector.size(); ++i)
	{
		if (m_pElementVector[i]->GetName() == sName)
			return m_pElementVector[i];
	}

	return NULL;
}


CEGUIElementBase * CEGUIContainer::GetElement(int nID) const
{
	for(unsigned int i=0; i < m_pElementVector.size(); ++i)
	{
		if (m_pElementVector[i]->GetID() == nID)
			return m_pElementVector[i];
	}

	return NULL;
}

CEGUIElementBase * CEGUIContainer::CreateElement(CEGUIElementType type)
{
	CEGUIElementBase * pElement = NULL;

	int id = CEGUIManager::GetSingleton()->GetNextID();
	string name = CEUtil::IntToStr(id);
	
	switch(type) {
	case GUI_Label:
		pElement = new CEGUILabel(this, id, name, "GE Game Engine ^o^");
		break;
	case GUI_PictureBox:
		pElement = new CEGUIPictureBox(this, id, name);
		break;
	case GUI_Container:
		pElement = new CEGUIContainer(this, id, name);
		break;
	case GUI_Button:
		pElement = new CEGUIButton(this, id, name);
		break;
	case GUI_ScrollBarHori:
		pElement = new CEGUIScrollBarHori(this, id, name);
		break;
	case GUI_ScrollBarVerti:
		pElement = new CEGUIScrollBarVertical(this, id, name);
		break;
	case GUI_TextBox:
		pElement = new CEGUITextBox(this, id, name, false);
		break;
	case GUI_CheckBox:
		pElement = new CEGUICheckBox(this, id, name);
		break;
	case GUI_RadioButton:
		pElement = new CEGUIRadioBox(this, id, name, "DEFAULT_GROUP");
		break;
	case GUI_DropdownList:
		pElement = new CEGUIDropdownList(this, id, name);
		break;
	case GUI_ListBox:
		pElement = new CEGUIListBox(this, id, name);
		break;
	case GUI_Animation:
		pElement = new CEGUIAnimation(this, name, 100);
		break;
	default:
		break;
	}
	
	if (pElement != NULL)
		m_pElementVector.push_back(pElement);
	
	return pElement;
}


void CEGUIContainer::DeleteAllElement()
{
	int size = m_pElementVector.size();
	for(int i = 0; i < size; ++i)
	{
		delete m_pElementVector[i];
	}
	m_pElementVector.clear();
}

bool CEGUIContainer::DeleteElement(int nID)
{
	vector<CEGUIElementBase *>::iterator p;
	for (p = m_pElementVector.begin(); p != m_pElementVector.end(); ++p)
	{
		if ((*p)->GetID() == nID)
		{
			delete (*p);
			*p = NULL;
			m_pElementVector.erase(p);
			return true;
		}
	}
	return false;
}

bool CEGUIContainer::DeleteElement(const string& sName)
{
	vector<CEGUIElementBase *>::iterator p;
	for (p = m_pElementVector.begin(); p != m_pElementVector.end(); ++p)
	{
		if ((*p)->GetName() == sName)
		{
			delete (*p);
			*p = NULL;
			m_pElementVector.erase(p);
			return true;
		}
	}
	return false;
}

bool CEGUIContainer::SetElementEnable(int nID, bool bEnable)
{
	CEGUIElementBase * pElement = GetElement(nID);
	if (pElement)
	{
		pElement->SetEnable(bEnable);
		return true;
	}

	return false;
}

bool CEGUIContainer::SetElementEnable(const string& sName, bool bEnable)
{
	CEGUIElementBase * pElement = GetElement(sName);
	if (pElement){
		pElement->SetEnable(bEnable);
		return true;
	}

	return false;
}



bool CEGUIContainer::SetElementVisible(const string& sName, bool bVisible)
{
	CEGUIElementBase * pElement = GetElement(sName);
	if (pElement){
		pElement->SetVisible(bVisible);
		return true;
	}

	return false;
}

bool CEGUIContainer::SetElementVisible(int nID, bool bVisible)
{
	CEGUIElementBase * pElement = GetElement(nID);
	if (pElement){
		pElement->SetVisible(bVisible);
		return true;
	}

	return false;
}



bool CEGUIContainer::IsElementEnable(int nID) const
{	
	CEGUIElementBase * pElement = GetElement(nID);
	if (pElement)
		return pElement->IsEnable();
	else
		return false;
}

bool CEGUIContainer::IsElementEnable(const string& sName) const
{	
	CEGUIElementBase * pElement = GetElement(sName);
	if (pElement)
		return pElement->IsEnable();
	else
		return false;
}

bool CEGUIContainer::IsElementVisible(int nID) const
{
	CEGUIElementBase * pElement = GetElement(nID);
	if (pElement)
		return pElement->IsVisible();
	else
		return false;
}

bool CEGUIContainer::IsElementVisible(const string& sName) const
{
	CEGUIElementBase * pElement = GetElement(sName);
	if (pElement)
		return pElement->IsVisible();
	else
		return false;
}


bool CEGUIContainer::SetElementPosition(const string& sName, int offsetX, int offsetY)
{
	CEGUIElementBase * pElement = GetElement(sName);
	if (pElement)
	{
		pElement->SetPosition(offsetX, offsetY);
		return true;
	}

	return false;
}

bool CEGUIContainer::SetElementPosition(int nID, int offsetX, int offsetY)
{
	CEGUIElementBase * pElement = GetElement(nID);
	if (pElement)
	{
		pElement->SetPosition(offsetX, offsetY);
		return true;
	}

	return false;
}


bool CEGUIContainer::SetElementSize(const string& sName, int width, int height)
{
	CEGUIElementBase * pElement = GetElement(sName);
	if (pElement)
	{
		pElement->SetSize(width, height);
		return true;
	}

	return false;
}


bool CEGUIContainer::SetElementSize(int nID, int width, int height)
{
	CEGUIElementBase * pElement = GetElement(nID);
	if (pElement)
	{
		pElement->SetSize(width, height);
		return true;
	}

	return false;
}


HRESULT CEGUIContainer::Render()
{
	HRESULT r = S_OK;

	if (m_bVisible)
	{
		SortElementInOrder();

		for(int i=0; i < m_pElementVector.size(); ++i)
		{
			r &= m_pElementVector[i]->Render();
		}
	}
	return r;
}

HRESULT CEGUIContainer::Update(float deltaTime)
{
	if (!m_bVisible)
		return S_FALSE;

	HRESULT r = S_OK;
	for(size_t i=0; i < m_pElementVector.size(); ++i)
	{
		r &= m_pElementVector[i]->Update(deltaTime);
	}

	return r;
}

HRESULT CEGUIContainer::OneTimeInit()
{
	HRESULT r = S_OK;
	int size = m_pElementVector.size();
	for(int i=0; i < size; ++i)
	{
		r &= m_pElementVector[i]->OneTimeInit();
	}
	return r;
}

void CEGUIContainer::FinalCleanUp()
{
	int size = m_pElementVector.size();
	for(int i = 0; i < size; ++i)
	{
		SAFE_DELETE(m_pElementVector[i]);
	}
	m_pElementVector.clear();
}


void CEGUIContainer::AddElement(CEGUIElementBase *element)
{
	if (element)
		m_pElementVector.push_back(element);
}

void CEGUIContainer::SaveInScrips(ofstream &fout, int level)
{
	string blank = "";
	int temp = level;
	while (temp--) blank += "\t\t";

	fout << endl;
	fout << blank << "<element_begin>" << endl;
	fout << blank << "\t" << "<Container>" << endl;

	if (m_strName != CEUtil::IntToStr(m_nID))
		fout << blank << "\t\t" << "<name>" << "\t" << m_strName << endl;
	fout << blank << "\t\t" << "<offset>" << "\t" << m_OffsetFromParent.x << "\t" << m_OffsetFromParent.y << endl;

	for (size_t i = 0; i < m_pElementVector.size(); ++i)
	{
		m_pElementVector[i]->SaveInScrips(fout, level+1);
	}

	fout << blank << "<element_end>" << endl;
}



void CEGUIContainer::SetPosition(int offsetFromParentX, int offsetFromParentY)
{
	CEGUIElementBase::SetPosition(offsetFromParentX, offsetFromParentY);
	for(size_t i = 0; i < m_pElementVector.size(); ++i)
	{
		m_pElementVector[i]->Move(0,0);
	}
}

void CEGUIContainer::Move(int offsetx, int offsety)
{
	CEGUIElementBase::Move(offsetx, offsety);
	for(size_t i = 0; i < m_pElementVector.size(); ++i)
	{
		m_pElementVector[i]->Move(0,0);
	}
}




void CEGUIContainer::SortElementInOrder()
{
	bool ordered;

	for (int i = 0; i < static_cast<int>(m_pElementVector.size())-1; ++i)
	{
		ordered = true;
		for (int j = 0; j < static_cast<int>(m_pElementVector.size())-1-i; ++j)
		{
			if (m_pElementVector[j]->GetShowLevel() > m_pElementVector[j+1]->GetShowLevel())
			{
				ordered = false;
				CEGUIElementBase* p = m_pElementVector[j];
				m_pElementVector[j] = m_pElementVector[j+1];
				m_pElementVector[j+1] = p;
			}
		}
		if (ordered)
			break;
	}
}
